package com.paw.ruoyi.admin.core.intercepter;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.paw.ruoyi.admin.common.annotion.Sign;
import com.paw.ruoyi.admin.common.constant.CommonConstant;
import com.paw.ruoyi.admin.common.domain.Result;
import com.paw.ruoyi.admin.common.enums.CommonResponseCodeEnum;
import com.paw.ruoyi.admin.common.utils.HttpResponseUtil;
import com.paw.ruoyi.admin.core.config.property.SignProperty;
import com.paw.ruoyi.admin.core.util.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * admin 权限拦截器
 * @author Rubble
 * @date 2021/9/3
 **/
@Slf4j
public class SignInterceptor implements HandlerInterceptor {

  private SignProperty signProperty;

  public SignInterceptor(SignProperty signProperty){
    this.signProperty = signProperty;
  }

  @Override
  public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if (!(handler instanceof HandlerMethod)) {
      return true;
    }
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    Sign accessSign = handlerMethod.getMethodAnnotation(Sign.class);
    if (accessSign == null && !accessSign.required()) {
      return true;
    }


    boolean success = checkSign(request);

    if(!success){
      Result<Object> result = Result.result(CommonResponseCodeEnum.FORBIDDEN);
      HttpResponseUtil.writeReturnJson(response, result);
    }

    return success;
  }


  private boolean checkSign(HttpServletRequest request){

    String signParam = request.getParameter(CommonConstant.SIGN_PARAM);
    String timestamp = request.getParameter(CommonConstant.TIME_PARAM);
    if(StrUtil.isBlank(timestamp) ||StrUtil.isBlank(signParam)){
      log.info("校验签名 缺少参数.");
      return false;
    }

    long requestTime = Long.parseLong(timestamp);
    long currentTime = System.currentTimeMillis();
    // 60s
    if(currentTime-requestTime> signProperty.getExpiredTime()){
      log.info("校验签名 请求时间戳过时.");
      return false;
    }

    Map<String, String[]> parameterMap = request.getParameterMap();
    String secret = signProperty.getSecret();

    String signStr = SignUtils.getSign(parameterMap, secret, timestamp);

    boolean success = signStr.equals(signParam);
    if(!success){
      log.info("校验签名 签名错误. params: {} secret: {} sign: {} timestamp: {}", JSON.toJSONString(parameterMap),secret,timestamp, signStr);
    }

    return true;
  }


}
